//
// Created by mio on 25-5-13.
//

#include "VideoConvert.h"

extern "C" {
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}

VideoConvert::VideoConvert() : width_(0), height_(0), format_(AV_PIX_FMT_NONE), swsContext_(nullptr)
{

}

VideoConvert::~VideoConvert()
{
    Close();
}

bool VideoConvert::Open(qint32 in_width, qint32 in_height, AVPixelFormat in_format, qint32 out_width, qint32 out_height,
    AVPixelFormat out_format) {
    if (swsContext_) return false;
    swsContext_ = sws_getContext(in_width, in_height, in_format,
                                out_width, out_height, out_format,
                                SWS_BICUBIC, nullptr, nullptr, nullptr);
    width_ = out_width;
    height_ = out_height;
    format_ = out_format;
    return swsContext_ != nullptr;
}

void VideoConvert::Close()
{
    if (swsContext_) {
        sws_freeContext(swsContext_);
        swsContext_ = nullptr;
    }
}

qint32 VideoConvert::Convert(AVFramePtr in_frame, AVFramePtr &out_frame)
{
    if (!swsContext_) return -1;

    out_frame.reset(av_frame_alloc(), [](AVFrame* p) { av_frame_free(&p); });

    out_frame->width = width_;
    out_frame->height = height_;
    out_frame->format = format_;
    out_frame->pts = in_frame->pts;
    out_frame->pkt_dts = in_frame->pkt_dts;

    if (av_frame_get_buffer(out_frame.get(), 0) != 0) return -1;

    uint32_t height_slice = sws_scale(swsContext_, in_frame->data, in_frame->linesize, 0,
                                in_frame->height, out_frame->data, out_frame->linesize);
    if (height_slice < 0) return -1;
    return height_slice;
}